#include <iostream>
#include <unistd.h>
#include <signal.h>
#include <cstring>
#include <sys/types.h>
#include <sys/wait.h>

using namespace std;

void Printpending()
{
    sigset_t pending;
    sigemptyset(&pending);
    sigpending(&pending);

    for (int signo = 31; signo >= 1; signo--)
    {
        if (sigismember(&pending, signo))
        {
            cout << "1";
        }
        else
        {
            cout << "0";
        }
    }
    cout << endl;
}

// //1.验证pending图中的信号什么时候被清空处理 -> 在调用处理方法之前就已经清零了
// // void handler(int signo)
// // {
// //     Printpending();
// //     cout << "recive signo: " << signo << endl;
// //     sleep(1);
// // }

// //2.验证OS在处理2号信号的时候，2号信号会被屏蔽
// void handler(int signo)
// {
//     while(true)
//     {
//         Printpending();
//         sleep(1);
//     }
// }

// int main()
// {

//     signal(2, handler);

//     while(true)
//     {
//         cout << "I am process: " << getpid() << endl;
//         sleep(1);
//     }

//     return 0;
// }

// 3.sigaction的使用
//   void handler(int signo)
//   {
//       while(true)
//       {
//           Printpending();
//           sleep(1);
//       }
//   }

// int main()
// {
//     //设置sigaction变量，并完成初始化
//     struct sigaction act, oldact;
//     memset(&act, 0, sizeof(act));
//     memset(&oldact, 0, sizeof(oldact));

//     //自定义捕捉函数
//     act.sa_handler = handler;

//     //我们希望在捕捉到2号信号的时候不仅屏蔽2号信号，也可以屏蔽其他信号，可以在act.sa_mask里面设置位图来达到该效果
//     sigset_t set, oldset;
//     sigemptyset(&set);
//     sigaddset(&set, 1);
//     sigaddset(&set, 3);
//     sigaddset(&set, 4);
//     sigaddset(&set, 5);
//     act.sa_mask = set;

//     sigaction(2, &act, &oldact);

//     while(true)
//     {
//         cout << "I am a process: " << getpid() << endl;
//         sleep(1);
//     }
//     return 0;
// }

// 4.从信号的角度理解volatile -> 保持内存的可见性
//  volatile int quit = 0;
//  void handler(int signo)
//  {
//      quit = 1;
//      cout << "recived signo: " << signo << endl;
//  }

// int main()
// {
//     signal(2, handler);
//     //quit可能会被优化成为register变量
//     while (!quit)
//     {
//         ;
//     }

//     return 0;
// }

// 5.a.利用信号进行单个进程的等待
// void handler(int signo)
// {
//     pid_t rid = waitpid(-1, nullptr, 0);
//     if (rid < 0)
//     {
//         cout << "wait failed" << endl;
//         exit(1);
//     }
// }
// int main()
// {
//     signal(2, handler);

//     pid_t id = fork();
//     if (id == 0)
//     {
//         // child
//         int cnt = 5;
//         while (cnt--)
//         {
//             cout << "I am child: " << getpid() << endl;
//             sleep(1);
//         }

//         exit(0);
//     }

//     // father
//     while (true)
//     {
//         cout << "I am father: " << getpid() << endl;
//         sleep(1);
//     }

//     return 0;
// }

// b. 利用信号回收多个子进程
//  void handler(int signo)
//  {
//      for(int i=0; i<5; i++)
//      {
//          pid_t rid = waitpid(-1, nullptr, 0);
//          if(rid < 0)
//          {
//              cout << "wait error" << endl;
//              exit(1);
//          }
//      }
//  }

// int main()
// {
//     signal(2, handler);

//     for (int i = 0; i < 5; i++)
//     {
//         pid_t id = fork();
//         if (id == 0)
//         {
//             // child
//             int cnt = 5;
//             while (cnt--)
//             {
//                 cout << "I am child" << i << ": " << getpid() << endl;
//                 sleep(1);
//             }

//             exit(0);
//         }
//     }

//     // father
//     while (true)
//     {
//         cout << "I am father: " << getpid() << endl;
//         sleep(1);
//     }

//     return 0;
// }

// c.利用进程等待回收任何想要的子进程
// void handler(int signo)
// {
//     sleep(5);
//     pid_t rid;
//     while (rid = waitpid(-1, nullptr, 0) > 0)
//     {
//         cout << "wait success: " << getpid() << endl;
//     }
// }

// int main()
// {
//     signal(17, handler);

//     for (int i = 0; i < 5; i++)
//     {
//         pid_t id = fork();
//         if (id == 0)
//         {
//             // child
//             int cnt = 5;
//             while (cnt--)
//             {
//                 cout << "I am child" << i << ": " << getpid() << endl;
//                 sleep(1);
//             }

//             exit(0);
//         }
//     }

//     // father
//     while (true)
//     {
//         cout << "I am father: " << getpid() << endl;
//         sleep(1);
//     }

//     return 0;
// }

int main()
{
    signal(17, SIG_IGN);

    pid_t id = fork();
    if (id == 0)
    {
        // child
        int cnt = 5;
        while (cnt--)
        {
            cout << "I am child: " << getpid() << endl;
            sleep(1);
        }

        exit(0);
    }

    while(true)
    {
        cout <<"I am father: " << getpid() << endl;
        sleep(1);
    }

    return 0;
}